package com.example.litehdfs.util;

import lombok.extern.slf4j.Slf4j;

import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

@Slf4j
@Component
public class RedisUtils {

    private static String localIP = "";

    public static final long MIN_15 = 15 * 60L;

    public static final long ONE_DAY = 1 * 24 * 60 * 60L;

    public static final long ONE_HOUR = 60 * 60L;

    public static final long ONE_WEEK = 7 * 24 * 60 * 60L;

    public static final long THREE_DAYS = 3 * 24 * 60 * 60L;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private Redisson redisson;
    
    private RedisTemplate<String, Object> getRedisTemplate(String key) {
        return redisTemplate;
    }

    /**
     * 设置 Object 类型 key-value
     *
     * @param key   redis key
     * @param value redis value
     * @return whether success
     */
    public boolean set(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            log.error("redis set error，key:[{}],value:[{}]", key, value, e);
            return false;
        }
    }

    /**
     * 获取 String 类型 key-value
     *
     * @param key
     * @return
     */
    public <T> T get(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return (T) redisTemplate.opsForValue().get(key);
    }

    /**
     * 设置 Object 类型 key-value,自定义时间和单位
     *
     * @param key   redis key
     * @param value redis value
     * @param time  time 时间 time要大于0 如果time小于等于0 将设置无限期
     * @param type  时间单位 TimeUnit
     * @return whether success
     */
    public boolean set(String key, Object value, long time, TimeUnit type) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, type);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            log.error("redis set error，key:[{}],value:[{}]", key, value, e);
            return false;
        }
    }

    /**
     * 设置 String 类型 key-value 并添加过期时间,key已经存在则返回false,不作更改
     *
     * @param key   redis key
     * @param value redis value
     * @param time  time 时间 time要大于0 如果time小于等于0 将设置无限期
     * @param type  时间单位 TimeUnit
     * @return true:key不存在，成功set false:key已存在，不做修改
     */
    public boolean setIfAbsent(String key, Object value, long time, TimeUnit type) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForValue().setIfAbsent(key, value, time, type);
    }

    /**
     * 对一个 key-value 的值进行加减操作,
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是长整型 ,将报错
     *
     * @param key
     * @param number
     */
    public Long increment(String key, long number) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForValue().increment(key, number);
    }


    /**
     * 给一个指定的 key 值重置过期时间
     *
     * @param key
     * @param time
     * @param type
     * @return whether success
     */
    public boolean expire(String key, long time, TimeUnit type) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.expire(key, time, type);
    }

    /**
     * 指定key在指定的日期过期
     *
     * @param key
     * @param date 过期的时间点
     * @return whether success
     */
    public boolean expireAt(String key, Date date) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.expireAt(key, date);
    }


    /**
     * 获取指定key 的过期时间
     *
     * @param key
     * @param timeUnit 时间单位
     * @return
     */
    public Long getExpire(String key, TimeUnit timeUnit) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.getExpire(key, timeUnit);
    }

    /**
     * 删除 key-value
     *
     * @param key
     * @return
     */
    public boolean delete(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.delete(key);
    }


    //List 操作

    /**
     * 指定 list 从左入栈一个元素
     *
     * @param key
     * @return 当前队列的长度
     */
    public Long leftPush(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 指定 list 从左出栈一个元素
     * 如果列表没有元素,会堵塞到列表一直有元素或者超时为止
     *
     * @param key
     * @return 出栈的值
     */
    public <T> T leftPop(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return (T) redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 从左边依次入栈
     * 导入顺序按照 Collection 顺序
     * 如: a b c => c b a
     *
     * @param key
     * @param values
     * @return
     */
    public Long leftPushAll(String key, Collection<Object> values) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForList().leftPushAll(key, values);
    }

    /**
     * 指定 list 从右入栈
     *
     * @param key
     * @return 当前队列的长度
     */
    public Long rightPush(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 指定 list 从右出栈
     * 如果列表没有元素,会堵塞到列表一直有元素或者超时为止
     *
     * @param key
     * @return 出栈的值
     */
    public <T> T rightPop(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return (T) redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 从右边依次入栈
     * 导入顺序按照 Collection 顺序
     * 如: a b c => a b c
     *
     * @param key
     * @param values
     * @return
     */
    public Long rightPushAll(String key, Collection<Object> values) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForList().rightPushAll(key, values);
    }


    /**
     * 获取列表 指定范围内的所有值
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForList().range(key, start, end);
    }


    //set 操作  无序不重复集合

    /**
     * 添加 set 元素
     *
     * @param key
     * @param values
     * @return
     */
    public Long sSet(String key, Object... values) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForSet().add(key, values);
    }


    /**
     * 删除一个或多个集合中的指定值
     *
     * @param key
     * @param values
     * @return 成功删除数量
     */
    public Long remove(String key, Object... values) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 无序集合的大小
     *
     * @param key
     * @return
     */
    public Long sGetSize(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 判断 set 集合中 是否有 value
     *
     * @param key
     * @param value
     * @return
     */
    public boolean sHasKey(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 返回集合中所有元素
     *
     * @param key
     * @return
     */
    public Set<Object> sGet(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForSet().members(key);
    }

    //Zset 根据 socre 排序   不重复 每个元素附加一个 socre  double类型的属性(double 可以重复)

    /**
     * 添加 ZSet 元素
     *
     * @param key
     * @param value
     * @param score
     */
    public boolean zAdd(String key, Object value, double score) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 获取 key 中指定 value 的排名(从0开始,从小到大排序)
     *
     * @param key
     * @param value
     * @return
     */
    public Long zRank(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().rank(key, value);
    }

    /**
     * 查看zset集合的成员个数
     *
     * @param key
     * @return
     */
    public Long zCard(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().zCard(key);
    }

    /**
     * 获取 key 中指定 value 的排名(从0开始,从大到小排序)
     *
     * @param key
     * @param value
     * @return
     */
    public Long reverseRank(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().reverseRank(key, value);
    }

    /**
     * 获取索引区间内的排序结果集合(从0开始,从大到小,带上分数)
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<ZSetOperations.TypedTuple<Object>> reverseRangeWithScores(String key, long start, long end) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
    }

    /**
     * 获取指定成员的 score 值
     *
     * @param key
     * @param value
     * @return
     */
    public Double zScore(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().score(key, value);
    }

    /**
     * zset 指定value加上score值
     *
     * @param key
     * @param value
     * @param score
     * @return
     */
    public Double zIncrementScore(String key, Object value, double score) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().incrementScore(key, value, score);
    }

    /**
     * zset 移除元素根据元素值。
     *
     * @param key
     * @param value
     * @return
     */
    public Long zRemove(String key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForZSet().remove(key, value);
    }

    /**
     * 删除指定大key 非阻塞版删除key
     * UNLINK	        DEL
     * FLUSHALL ASYNC	FLUSHALL
     * FLUSHDB ASYNC	FLUSHDB
     */
    public Boolean unlink(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.unlink(key);
    }

    /**
     * `     * 设置HyperLogLog的key和value
     *
     * @param key
     * @param value
     * @return
     */
    public Long pfadd(String key, String value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForHyperLogLog().add(key, value);
    }

    /**
     * HyperLogLog 统计数量
     *
     * @param key
     * @return
     */
    public Long pfCount(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForHyperLogLog().size(key);
    }

    /**
     * 位图操作
     *
     * @param key
     * @param offset
     * @param value
     * @return
     */
    public Boolean setBit(String key, long offset, Boolean value) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForValue().setBit(key, offset, value);
    }

    /**
     * 位图操作
     *
     * @param key
     * @param offset
     * @return
     */
    public Boolean getBit(String key, long offset) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.opsForValue().getBit(key, offset);
    }

    public Long bitCount(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return (Long) redisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes()));
    }

    /**
     * 设置一个key的过期时间（单位：秒）
     *
     * @param key     key值
     * @param seconds 多少秒后过期
     * @return 1：设置了过期时间 0：没有设置过期时间/不能设置过期时间
     */
    public boolean expire(String key, long seconds) {
        if (key == null || "".equals(key)) {
            return false;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            // 都为秒,
            return redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
        } else {
            return false;
        }
    }

    /**
     * 设置一个key的过期时间（单位：秒）
     *
     * @param key      key值
     * @param unixTime 多少秒后过期
     * @return 1：设置了过期时间 0：没有设置过期时间/不能设置过期时间
     */
    public boolean expireAt(String key, long unixTime) {
        if (key == null || "".equals(key)) {
            return false;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.expireAt(key, new Date(unixTime));
        } else {
            return false;
        }

    }


    /**
     * 设置一个key,值+1
     *
     * @param key
     * @return
     */
    public long incr(String key) {
        if (key == null || "".equals(key)) {
            return 0;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForValue().increment(key);
        } else {
            return 0;
        }

    }

    /**
     * 设置一个key,值-1
     *
     * @param key
     * @return
     */
    public long decr(String key) {
        if (key == null || "".equals(key)) {
            return 0;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForValue().decrement(key);
        } else {
            return 0;
        }
    }


    /**
     * 设key值
     *
     * @param key
     * @param value
     * @return
     */
    public <T> boolean setEx(String key, long outTime, T value) {
        if (key == null || "".equals(key)) {
            return false;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            redisTemplate.opsForValue().set(key, value, outTime, TimeUnit.SECONDS);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 取key值 , 不存在则返回默认值
     *
     * @param key
     * @param defaultValue
     * @return
     */
    public <T> T get(String key, T defaultValue) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        Object value = redisTemplate.opsForValue().get(key);
        if (value != null) {
            return (T) value;
        } else {
            return defaultValue;
        }
    }

    /**
     * 如果不存在，则 SET值
     *
     * @param key
     * @param value
     * @return
     */
    public <T> Boolean setnx(String key, T value) {
        if (key == null || "".equals(key)) {
            return false;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForValue().setIfAbsent(key, value);
        } else {
            return false;
        }
    }

//    public <T> Boolean setnx(final String key, final T value) {
//        if (key == null || key.equals("")) {
//            return false;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
//                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
//                    return connection.setNX(key.getBytes(), redisTemplate.getValueSerializer().serialize(value));
//                }
//            });
//        } else {
//            return false;
//        }
//    }

    public <T> Boolean setNx(String key, T value, long time, TimeUnit type) {
        if (key == null || "".equals(key)) {
            return false;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForValue().setIfAbsent(key, value, time, type);
        } else {
            return false;
        }
    }


    /**
     * 删除key
     *
     * @param key
     * @return
     */
    public long del(String key) {
        if (key == null || "".equals(key)) {
            return 0;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            Boolean delete = redisTemplate.delete(key);
            if (delete != null && delete) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * list插入 *
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long lPush(String key, T value) {
        if (key == null || "".equals(key)) {
            return 0;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForList().leftPush(key, value);
        } else {
            return 0;
        }
    }

    /**
     * list 插入集合
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long lPushList(String key, List<T> value) {
        if (key == null || "".equals(key)) {
            return 0;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForList().leftPushAll(key, value);
        } else {
            return 0;
        }
    }

    /**
     * list 弹出
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> T lPop(String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (T) redisTemplate.opsForList().leftPop(key);
        } else {
            return null;
        }
    }

    /**
     * list 获取所有了!
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> List<T> lRange(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForList().range(key, 0, -1);
        } else {
            return null;
        }

    }

    /**
     * set 添加值
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long sAdd(String key, T value) {
        if (key == null || "".equals(key)) {
            return 0;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForSet().add(key, value);
        } else {
            return 0;
        }
    }

//    public <T> long sAdd(final String key, final T value) {
//        if (key == null || key.equals("")) {
//            return 0;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return (Long) redisTemplate.execute(new RedisCallback<Long>() {
//                public Long doInRedis(RedisConnection connection) throws DataAccessException {
//                    return connection.sAdd(key.getBytes(), redisTemplate.getValueSerializer().serialize(value));
//                }
//            });
//        } else {
//            return 0;
//        }
//    }

    /**
     * 删除set的元素
     *
     * @param key
     * @param value
     * @return
     */
    public Long srem(String key, String value) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForSet().remove(key, value);
        } else {
            return null;
        }
    }

    /**
     * 弹出set的值
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> T sPop(String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (T) redisTemplate.opsForSet().pop(key);
        } else {
            return null;
        }
    }

    /**
     * 获取全部数据
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> Set<T> sMembers(String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForSet().members(key);
        } else {
            return null;
        }
    }

    /**
     * hash 添加
     *
     * @param key
     * @param field
     * @param value
     * @param <T>
     * @return
     */
    public <T> Boolean hSet(final String key, final String field, final T value) {
        if (key == null || "".equals(key)) {
            return false;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key + field);
        if (redisTemplate != null) {
            redisTemplate.opsForHash().put(key, field, value);
            return true;
        } else {
            return false;
        }
    }

//    public <T> Boolean hSet(final String key, final String field, final T value) {
//        if (key == null || key.equals("")) {
//            return false;
//        }
//        final String newkey = getHsetKey(key);
//        RedisTemplate redisTemplate = getRedisTemplate(newkey+field);
//        if (redisTemplate != null) {
//            return (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
//                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
//                    return connection.hSet(newkey.getBytes(), field.getBytes(), redisTemplate.getValueSerializer().serialize(value));
//                }
//            });
//        } else {
//            return false;
//        }
//    }


    /**
     * hash 获取值
     *
     * @param key
     * @param field
     * @param <T>
     * @return
     */
    public <T> T hGet(String key, String field) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key + field);
        if (redisTemplate != null) {
            return (T) redisTemplate.opsForHash().get(key, field);
        } else {
            return null;
        }
    }

    public Map hGetAll(final String key) {
        if (key == null || key.equals("")) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForHash().entries(key);
        } else {
            return null;
        }
    }

    public Long hIncrby(final String key, final String field, final Long value) {
        if (key == null || key.equals("")) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key + field);
        if (redisTemplate != null) {
            return redisTemplate.opsForHash().increment(key, field, value);
        } else {
            return null;
        }
    }

    /**
     * hash 删除
     *
     * @param key
     * @param field
     * @return
     */
    public Long hFieldDel(String key, String field) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key + field);
        if (redisTemplate != null) {
            return redisTemplate.opsForHash().delete(key, field);
        } else {
            return null;
        }
    }


    /**
     * 删除集群上所有Hset key
     *
     * @param key
     * @return
     */
    /*public long hKeyDelFromCluster(final String key) {
        long delKeys = 0;
        if (key == null || "".equals(key)) {
            return delKeys;
        }
        for (Map.Entry<RedisTemplate, Boolean> entity : redisTemplateMap.entrySet()) {
            if (entity.getValue()) {
                RedisTemplate redisTemplate = entity.getKey();
                if (redisTemplate != null) {
                    delKeys += (Long) redisTemplate.execute(new RedisCallback<Long>() {
                        public Long doInRedis(RedisConnection connection) throws DataAccessException {
                            return connection.unlink(key.getBytes());
                        }
                    });
                }
            }
        }
        return delKeys;
    }*/


    /**
     * 删除集群上所有Hset key
     *
     * @param key
     * @return
     */
    /*public long hKeyDel(final String key) {
        long delKeys = 0;
        if (key == null || "".equals(key)) {
            return delKeys;
        }
        for (Map.Entry<RedisTemplate, Boolean> entity : redisTemplateMap.entrySet()) {
            if (entity.getValue()) {
                RedisTemplate redisTemplate = entity.getKey();
                if (redisTemplate != null) {
                    delKeys += (Long) redisTemplate.execute(new RedisCallback<Long>() {
                        public Long doInRedis(RedisConnection connection) throws DataAccessException {
                            return connection.unlink(key.getBytes());
                        }
                    });
                }
            }
        }
        return delKeys;
    }*/
    public boolean hKeyExpire(String key, String field, long seconds) {
        if (key != null && !"".equals(key)) {
            RedisTemplate redisTemplate = getRedisTemplate(key + field);
            return redisTemplate != null ? redisTemplate.expire(key, seconds, TimeUnit.SECONDS) : false;
        } else {
            return false;
        }
    }

    /**
     * 遍历每个redis节点，各个hlen结果求和
     */
    /*public Long hLen(final String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        Long sum = 0L;
        List<RedisTemplate> redisTemplates = consistentHash.getShards();
        List<String> addressPorts = new ArrayList<String>();
        for (RedisTemplate redisTemplate : redisTemplates) {
            if (redisTemplate != null) {
                // 测试环境配置addressPort都一样，会导致重复统计，这里增加去重
                LettuceConnectionFactory connectionFactory = ((LettuceConnectionFactory) redisTemplate
                        .getConnectionFactory());
                String addressPort = connectionFactory.getHostName() + "_" + connectionFactory.getPort();
                if (!addressPorts.contains(addressPort)) {
                    sum += (Long) redisTemplate.execute(new RedisCallback<Long>() {
                        public Long doInRedis(RedisConnection connection) throws DataAccessException {
                            return connection.hLen(key.getBytes());
                        }
                    });
                    addressPorts.add(addressPort);
                }
            }
        }

        return sum;
    }*/

    /**
     * 获取key过期时间
     *
     * @param key
     * @return
     */
    public long ttl(final String key) {
        if (key == null || "".equals(key)) {
            return 0;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.getExpire(key);
        } else {
            return -1;
        }
    }

    /**
     * zAdd
     *
     * @param key
     * @return
     */
//    public Boolean zAdd(String key, double score, String value) {
//        if (key == null || "".equals(key)) {
//            return false;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return redisTemplate.opsForZSet().add(key, value, score);
//        } else {
//            return false;
//        }
//    }
    public Boolean zAdd(final String key, final double score, final String value) {
        if (key == null || key.equals("")) {
            return false;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.zAdd(key.getBytes(), score, value.getBytes());
                }
            });
        } else {
            return false;
        }
    }

    /**
     * zRangeWithScores
     * zrange key start stop [WITHSCORES] 获取全部数据 (从start看到stop 全部0 和-1)
     * ([WITHSCORES] 带上了排序字段值)   (升序)
     *
     * @param key
     * @return
     */
//    public Set<RedisZSetCommands.Tuple> zRevRangeWithScores(String key, long begin, long end) {
//        if (key == null || "".equals(key)) {
//            return null;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return redisTemplate.opsForZSet().reverseRangeWithScores(key, begin, end);
//        } else {
//            return null;
//        }
//    }
    public Set<RedisZSetCommands.Tuple> zRevRangeWithScores(final String key, final long begin, final long end) {
        if (key == null || key.equals("")) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (Set<RedisZSetCommands.Tuple>) redisTemplate.execute(new RedisCallback<Set<RedisZSetCommands.Tuple>>() {
                public Set<RedisZSetCommands.Tuple> doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.zRevRangeWithScores(key.getBytes(), begin, end);
                }
            });
        } else {
            return null;
        }
    }

    /* zScore
     zscore key member  score值获取 获取(获取member的)
     *
     * @param key
     * @return
     */
//    public Double zScore(String key, String value) {
//        if (key == null || "".equals(key)) {
//            return null;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return redisTemplate.opsForZSet().score(key, value);
//        } else {
//            return null;
//        }
//    }

    public Double zScore(final String key, final String value) {
        if (key == null || key.equals("")) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (Double) redisTemplate.execute(new RedisCallback<Double>() {
                public Double doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.zScore(key.getBytes(), value.getBytes());
                }
            });
        } else {
            return null;
        }
    }

    /* zRank
     *
     * @param key
     * @return
     */
//    public Long zRevRank(String key, String value) {
//        if (key == null || "".equals(key)) {
//            return null;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return redisTemplate.opsForZSet().rank(key, value);
//        } else {
//            return null;
//        }
//    }

    public Long zRevRank(final String key, final String value) {
        if (key == null || key.equals("")) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (Long) redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.zRevRank(key.getBytes(), value.getBytes());
                }
            });
        } else {
            return null;
        }
    }

    /**
     * 可能有问题
     * 移除有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。
     *
     * @param key
     * @param begin
     * @param end
     * @return
     */
//    public Long zRemRangeByScore(String key, double begin, double end) {
//        if (key == null || "".equals(key)) {
//            return null;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return redisTemplate.opsForZSet().removeRangeByScore(key,begin,end);
//        } else {
//            return null;
//        }
//    }
    public Long zRemRangeByScore(final String key, final double begin, final double end) {
        if (key == null || key.equals("")) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (Long) redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.zRemRangeByScore(key.getBytes(), begin, end);
                }
            });
        } else {
            return null;
        }
    }

    /* zRank
     *
     * @param key
     * @return
     */
//    public Long zRemove(String key, String zkey) {
//        if (key == null || "".equals(key)) {
//            return null;
//        }
//        RedisTemplate redisTemplate = getRedisTemplate(key);
//        if (redisTemplate != null) {
//            return redisTemplate.opsForZSet().remove(key, zkey);
//        } else {
//            return null;
//        }
//    }

    public Long zRemove(final String key, final String zkey) {
        if (key == null || key.equals("")) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return (Long) redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.zRem(key.getBytes(), zkey.getBytes());
                }
            });
        } else {
            return null;
        }
    }

    /* setBit
     *
     * @param key
     * @return
     */
    public Boolean setBit(String key, long offset) {
        if (key == null || "".equals(key)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(key);
        if (redisTemplate != null) {
            return redisTemplate.opsForValue().setBit(key, offset, true);
        } else {
            return null;
        }
    }

    /* zRank
     *
     * @param key
     * @return
     */
    /*public Boolean scanAndDel(final String match, final int count) {
        for (Map.Entry<RedisTemplate, Boolean> entity : redisTemplateMap.entrySet()) {
            if (entity.getValue()) {
                RedisTemplate redisTemplate = entity.getKey();
                if (redisTemplate != null) {
                    redisTemplate.execute(new RedisCallback<Boolean>() {
                        public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                            ScanOptions.ScanOptionsBuilder options = new ScanOptions.ScanOptionsBuilder();
                            options.count(count);
                            options.match(match);
                            Cursor<byte[]> scanResult = connection.scan(options.build());
                            while (scanResult.hasNext()) {
                                byte[] entry = scanResult.next();
                                long time = connection.ttl(entry);
                                if (time == -1) {
                                    connection.del(entry);
                                }
                            }
                            return null;
                        }
                    });
                }
            }
        }
        return null;
    }*/

    /* publish
     *
     * @param key
     * @return
     */
    public Long publish(final String channel, final String message) {
        if (channel == null || "".equals(channel)) {
            return null;
        }
        RedisTemplate redisTemplate = getRedisTemplate(channel);
        if (redisTemplate != null) {
            return (Long) redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.publish(channel.getBytes(), message.getBytes());
                }
            });
        } else {
            return null;
        }
    }

    /* subscribe
     *
     * @param key
     * @return
     */
    public void subscribe(final String channel, final MessageListener listener) {
        RedisTemplate redisTemplate = getRedisTemplate(channel);
        if (redisTemplate != null) {
            redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.subscribe(listener, channel.getBytes());
                    return null;
                }
            });
        }
    }


    /**
     * lua脚本
     */
    /*public void luaScriptPurge(final String luaScript, int numKeys, byte[]... keysAndArgs) {
        for (RedisTemplate redisTemplate : redisTemplates) {
            redisTemplate.execute(new RedisCallback() {
                @Override
                public Object doInRedis(RedisConnection con) throws DataAccessException {
                    List<byte[]> eval = con.eval(luaScript.getBytes(), ReturnType.MULTI, numKeys, keysAndArgs);
                    if (eval != null && eval.size() > 0) {
                        for (byte[] bytes : eval) {
                            log.info("redis auto purge:" + new String(bytes));
                        }
                    }
                    return eval;
                }
            });
        }
    }*/
    public Boolean exist(String key) {
        RedisTemplate redisTemplate = getRedisTemplate(key);
        return redisTemplate.hasKey(key);
    }
    
    public boolean tryLock(String lockKey, long expirationTime) {
        final RBucket<String> bucket = redisson.getBucket(lockKey);
        return bucket.setIfAbsent("1", Duration.ofMinutes(expirationTime));
    }
    
    public void unLock(String lockKey){
        final RBucket<String> bucket = redisson.getBucket(lockKey);
        bucket.delete();
    }


}